package com.wesley.zk;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * 模拟配置中心
 */
@Slf4j
public class ConfigCenter {

    private final static String CONNECT_STR = "192.168.223.128:2181";

    /**
     * 会话的超时时间，是一个以“毫秒”为单位的整型值。在ZooKeeper中有会话的概念，
     * 在一个会话周期内，ZooKeeper客户端和服务器之间会通过心跳检测机制来维持会话的有效性，
     * 一旦在sessionTimeout时间内没有进行有效的心跳检测，会话就会失效。
     */
    private final static Integer SESSION_TIMEOUT = 30 * 1000;

    private final static String PATH = "/wesley/config";

    private static ZooKeeper zooKeeper = null;


    private final static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {


        zooKeeper = new ZooKeeper(CONNECT_STR, SESSION_TIMEOUT, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                if (event.getType() == Event.EventType.None
                        && event.getState() == Event.KeeperState.SyncConnected) {
                    log.info("连接已建立");
                    countDownLatch.countDown();
                }
            }
        });
        countDownLatch.await();


        MyConfig myConfig = new MyConfig();
        myConfig.setKey("anyKey");
        myConfig.setName("anyName");

        ObjectMapper objectMapper = new ObjectMapper();

        byte[] bytes = objectMapper.writeValueAsBytes(myConfig);

        String s = zooKeeper.create(PATH, bytes, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);


        Watcher watcher = new Watcher() {
            @SneakyThrows
            @Override
            public void process(WatchedEvent event) {
                if (event.getType() == Event.EventType.NodeDataChanged
                        && event.getPath() != null && event.getPath().equals(PATH)) {
                    log.info(" PATH:{}  发生了数据变化", event.getPath());

                    byte[] data = zooKeeper.getData(PATH, this, null);

                    MyConfig newConfig = objectMapper.readValue(new String(data), MyConfig.class);

                    log.info("数据发生变化: {}", newConfig);

                }
            }
        };

        byte[] data = zooKeeper.getData(PATH, watcher, null);
        MyConfig originalMyConfig = objectMapper.readValue(new String(data), MyConfig.class);
        log.info("原始数据: {}", originalMyConfig);


        TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
    }


}
